#ifndef PROCESSOR_H
#define PROCESSOR_H
#include <glib.h>
#include "event.h"

typedef struct ProvEdge {
    struct ProvNode *from;
    struct ProvNode *to;
    gboolean critical; // BFS PATH
    gchar * type;
} ProvEdge;

typedef struct ProvNode  {
    guint id;
    gboolean active; 
    gchar * host;
    gchar * type;
    gchar * name;
    GSList *in; // ProvNode
    GSList *out;
    struct ProvNode* next; // NextNode
    void *opaque;
    gboolean *has_ctx; // note: we need to add identifier later
} ProvNode;

typedef struct ProvGraph {
    GPtrArray *prov_nodes;
    GPtrArray *prov_edges;
    guint id_base;
    GHashTable * node_map;
} ProvGraph;

typedef struct Processor {
    void *opaque;
    ProvGraph g;
    int (*process) (void *opaque, Event *e);
    void (*destructor) (void *opaque);
} Processor;

/* from->to */
typedef int(TravelCB) (void *opaque, ProvNode *from, ProvNode *to,  gchar *edge_type);

Processor * processor_create (void *opaque, void(*destructor)(void*), GHashFunc hfunc, GEqualFunc efunc);

static inline int processor_process (Processor *p, Event *e) {
    return p->process (p->opaque, e);
}

void processor_destructor (Processor *p);

/*if @in is true, we will traverse the graph until we visit all source nodes */
int processor_traverse (Processor *p, void *gen,  gchar *host,  gchar *name,  gchar *type, gboolean in, TravelCB *cb);

int processor_traverse_regex (Processor *p, void *gen, gchar *host_rx_str,  gchar *name_rx_str,  gchar * type,gboolean in, TravelCB *cb);

int processor_traverse_regex_bidirectional (Processor *p, void *gen,gchar *host_rx_str,  gchar *name_rx_str,  gchar * type, TravelCB *cb);

int processor_traverse_regex_point2point (Processor *p, void *gen, gchar *src_host_rx_str,  gchar *src_name_rx_str,  gchar * src_type, gchar *tgt_host_rx_str,  gchar *tgt_name_rx_str,  gchar * tgt_type,TravelCB *cb);

/* traverse all nodes */
int processor_traverse_all (Processor *p, void *gen,  TravelCB *cb);

ProvNode * prov_node_find_active (Processor *pr, ProvNode * hint);

ProvNode * prov_node_insert (Processor *p,  gchar * host,   gchar * type,  gchar *name) ;

int prov_node_terminate (Processor *p,  gchar * host,  gchar * type,  gchar *name);

int prov_node_connect (Processor *p, ProvNode *from, ProvNode *to,  gchar * type);

Processor * optc_processor_create ();

#endif